﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using MacomberMapSystem.Common.Serialization;
using MacomberMapSystem.Common.Database;

namespace MacomberMapSystem.Common.User_Interfaces.Database
{
    /// <summary>
    /// This form displays a dialog box, allowing the user to select a model
    /// </summary>
    public partial class frmSelectModel : Form
    {
        #region Variable declarations
        /// <summary>Our collection of active models</summary>
        public List<MM_Database_Model> ActiveModels = new List<MM_Database_Model>();

        /// <summary>Our repository</summary>
        public MM_Repository Repository;

        /// <summary>Our selected model</summary>
        public MM_Database_Model SelectedModel = null;

        /// <summary>Whether our form is updating</summary>
        private bool Updating = false;

        /// <summary>Whether the model should be opened in direct mode</summary>
        public bool DirectMode = false;
        #endregion

        /// <summary>
        /// Initialize our model selector
        /// </summary>
        /// <param name="Repository"></param>
        public frmSelectModel(MM_Repository Repository)
        {
            InitializeComponent();
            this.Repository = Repository;
            ActiveModels.AddRange(Repository.Model_Collection.Values);
            cmbModelCategory.Items.Add("All");
            foreach (MM_Database_Model Mod in Repository.Model_Collection.Values)
                if (!cmbModelCategory.Items.Contains(Mod.ModelCategory))
                    cmbModelCategory.Items.Add(Mod.ModelCategory);
            cmbModelCategory.SelectedIndex = 0;
        }

        /// <summary>
        /// Update our displays based on our current collection of active models
        /// </summary>
        public void UpdateDisplays()
        {
            if (Updating)
                return;
            Updating = true;
            List<DateTime> SelDates = new List<DateTime>();
            foreach (MM_Database_Model Mod in ActiveModels)// Repository.Model_Collection.Values)
                if (!SelDates.Contains(Mod.ValidStart))
                    SelDates.Add(Mod.ValidStart);
            SelDates.Sort();

            //Adjust our date boundaries to fit
            if (SelDates.Count > 0)
            {
                if (calModel.MinDate > SelDates[SelDates.Count - 1])
                    calModel.MinDate = SelDates[SelDates.Count - 1];
                calModel.MaxDate = SelDates[SelDates.Count - 1];
                calModel.MinDate = SelDates[0];
                calModel.SelectionStart = calModel.SelectionEnd = SelDates[SelDates.Count - 1];
                calModel.BoldedDates = SelDates.ToArray();
            }

            Updating = false;
        }

        /// <summary>
        /// Update our active model collection based on components
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void cmbModelCategory_SelectedIndexChanged(object sender, EventArgs e)
        {
            ActiveModels.Clear();
            cmbModelClass.Items.Clear();
            cmbModelClass.Text = "";
            cmbModel.Items.Clear();
            cmbModel.Text = "";

            SortedDictionary<int, MM_Database_Model> SortedModels = new SortedDictionary<int, MM_Database_Model>();
            foreach (MM_Database_Model Model in Repository.Model_Collection.Values)
                if (Model.ModelCategory == (string)cmbModelCategory.SelectedItem || (string)cmbModelCategory.SelectedItem == "All")
                {
                    SortedModels.Add(-Model.ID, Model);
                    ActiveModels.Add(Model);                    
                }

            cmbModelClass.Items.Clear();
            foreach (MM_Database_Model Model in SortedModels.Values)
                if (!cmbModelClass.Items.Contains(Model.ModelClass))
                    cmbModelClass.Items.Add(Model.ModelClass);
            

            if (!Updating)
                UpdateDisplays();
        }

        /// <summary>
        /// Update our selection of models based on the selected category
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void cmbModelClass_SelectedIndexChanged(object sender, EventArgs e)
        {

            ActiveModels.Clear();
            cmbModel.Items.Clear();
            cmbModel.Text = "";
            SortedDictionary<int, String> SortedModels = new SortedDictionary<int, String>();
            SortedDictionary<int, MM_Database_Model> SortedActualModels = new SortedDictionary<int, MM_Database_Model>();

            foreach (MM_Database_Model Mod in Repository.Model_Collection.Values)
                if ((Mod.ModelCategory == (string)cmbModelCategory.SelectedItem || (string)cmbModelCategory.Text == "All") && Mod.ModelClass == (string)cmbModelClass.SelectedItem)
                {
                    ActiveModels.Add(Mod);
                    SortedModels.Add(-Mod.ID, Mod.FullClass);
                    SortedActualModels.Add(-Mod.ID, Mod);
                }
            cmbModel.Items.AddRange(SortedModels.Values.ToArray());
            cmbModel.Tag = SortedActualModels.Values.ToArray();

            if (!Updating)
                UpdateDisplays();
        }

        /// <summary>
        /// Update our list of options available when a user clicks on a date
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void calModel_DateChanged(object sender, DateRangeEventArgs e)
        {
            if (Updating)
                return;
            Updating = true;
            MM_Database_Model SelModel = null;
            DateTime MinDate = DateTime.MinValue;
            foreach (MM_Database_Model Mod in Repository.Model_Collection.Values)
                if (Mod.ValidStart <= e.Start.Date && Mod.ValidStart > MinDate)
                {
                    SelModel = Mod;
                    MinDate = Mod.ValidStart;
                }
            if (SelModel != null)
                {
                    cmbModelCategory.SelectedItem = SelModel.ModelCategory;
                    cmbModelClass.SelectedItem = SelModel.ModelClass;
                    cmbModel.SelectedItem = SelModel.FullClass;
                    SelectedModel = SelModel;
                }
            Updating = false;
        }

        /// <summary>
        /// Handle the selection of our model
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void cmbModel_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (cmbModel.SelectedIndex == -1)
                SelectedModel = null;
            else
            {
                MM_Database_Model[] Model = (MM_Database_Model[])cmbModel.Tag;
                SelectedModel = Model[cmbModel.SelectedIndex];
            }
        }

        /// <summary>
        /// Handle the ok button
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnOk_Click(object sender, EventArgs e)
        {
            if (SelectedModel == null)
                MessageBox.Show("Please select a model.", Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
            else
            {
                DialogResult = DialogResult.OK;
                DirectMode = true;
                this.Close();
            }
        }

        /// <summary>
        /// Handle the cancel button
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnCancel_Click(object sender, EventArgs e)
        {
            SelectedModel = null;
            DialogResult = DialogResult.Cancel;
            this.Close();
        }

        /// <summary>
        /// Handle the open direct mode
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnOpenDirect_Click(object sender, EventArgs e)
        {
            if (SelectedModel == null)
                MessageBox.Show("Please select a model.", Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
            else
            {
                DialogResult = DialogResult.OK;
                DirectMode = true;
                this.Close();
            }
        }

        /// <summary>
        /// When the 'already opened' dropdown is clicked, propigate accordingly
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void cmbAlreadyOpened_DropDown(object sender, EventArgs e)
        {
            cmbAlreadyOpened.Items.Clear();
            foreach (MM_Database_Model Model in Repository.Model_Collection.Values)
                if (Model.State == MM_Database_Model.enumModelState.Completed)
                    cmbAlreadyOpened.Items.Add(Model);
        }

        /// <summary>
        /// Select the intended model
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void cmbAlreadyOpened_SelectedIndexChanged(object sender, EventArgs e)
        {
            SelectedModel = cmbAlreadyOpened.SelectedItem as MM_Database_Model;
            if (SelectedModel == null)
                return;
            DirectMode = SelectedModel.DirectModel;
            DialogResult = DialogResult.OK;
        }
    }
}